home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / p_hud.c1 < prev    next >
Encoding:
Text File  |  2002-09-24  |  13.7 KB  |  572 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "g_local.h"
  21.  
  22.  
  23.  
  24. /*
  25. ======================================================================
  26.  
  27. INTERMISSION
  28.  
  29. ======================================================================
  30. */
  31.  
  32. void MoveClientToIntermission (edict_t *ent)
  33. {
  34.     if (deathmatch->value || coop->value)
  35.         ent->client->showscores = true;
  36.     VectorCopy (level.intermission_origin, ent->s.origin);
  37.     ent->client->ps.pmove.origin[0] = level.intermission_origin[0]*8;
  38.     ent->client->ps.pmove.origin[1] = level.intermission_origin[1]*8;
  39.     ent->client->ps.pmove.origin[2] = level.intermission_origin[2]*8;
  40.     VectorCopy (level.intermission_angle, ent->client->ps.viewangles);
  41.     ent->client->ps.pmove.pm_type = PM_FREEZE;
  42.     ent->client->ps.gunindex = 0;
  43.     ent->client->ps.blend[3] = 0;
  44.     ent->client->ps.rdflags &= ~RDF_UNDERWATER;
  45.  
  46.     // clean up powerup info
  47.     ent->client->quad_framenum = 0;
  48.     ent->client->invincible_framenum = 0;
  49.     ent->client->breather_framenum = 0;
  50.     ent->client->enviro_framenum = 0;
  51.     ent->client->grenade_blew_up = false;
  52.     ent->client->grenade_time = 0;
  53.  
  54.     ent->viewheight = 0;
  55.     ent->s.modelindex = 0;
  56.     ent->s.modelindex2 = 0;
  57.     ent->s.modelindex3 = 0;
  58.     ent->s.modelindex = 0;
  59.     ent->s.effects = 0;
  60.     ent->s.sound = 0;
  61.     ent->solid = SOLID_NOT;
  62.  
  63.     // add the layout
  64.  
  65.     if (deathmatch->value || coop->value)
  66.     {
  67.         DeathmatchScoreboardMessage (ent, NULL);
  68.         gi.unicast (ent, true);
  69.     }
  70.  
  71. }
  72.  
  73. void BeginIntermission (edict_t *targ)
  74. {
  75.     int        i, n;
  76.     edict_t    *ent, *client;
  77.  
  78.     if (level.intermissiontime)
  79.         return;        // already activated
  80.  
  81.     game.autosaved = false;
  82.  
  83.     // respawn any dead clients
  84.     for (i=0 ; i<maxclients->value ; i++)
  85.     {
  86.         client = g_edicts + 1 + i;
  87.         if (!client->inuse)
  88.             continue;
  89.         if (client->health <= 0)
  90.             respawn(client);
  91.     }
  92.  
  93.     level.intermissiontime = level.time;
  94.     level.changemap = targ->map;
  95.  
  96.     if (strstr(level.changemap, "*"))
  97.     {
  98.         if (coop->value)
  99.         {
  100.             for (i=0 ; i<maxclients->value ; i++)
  101.             {
  102.                 client = g_edicts + 1 + i;
  103.                 if (!client->inuse)
  104.                     continue;
  105.                 // strip players of all keys between units
  106.                 for (n = 0; n < MAX_ITEMS; n++)
  107.                 {
  108.                     if (itemlist[n].flags & IT_KEY)
  109.                         client->client->pers.inventory[n] = 0;
  110.                 }
  111.             }
  112.         }
  113.     }
  114.     else
  115.     {
  116.         if (!deathmatch->value)
  117.         {
  118.             level.exitintermission = 1;        // go immediately to the next level
  119.             return;
  120.         }
  121.     }
  122.  
  123.     level.exitintermission = 0;
  124.  
  125.     // find an intermission spot
  126.     ent = G_Find (NULL, FOFS(classname), "info_player_intermission");
  127.     if (!ent)
  128.     {    // the map creator forgot to put in an intermission point...
  129.         ent = G_Find (NULL, FOFS(classname), "info_player_start");
  130.         if (!ent)
  131.             ent = G_Find (NULL, FOFS(classname), "info_player_deathmatch");
  132.     }
  133.     else
  134.     {    // chose one of four spots
  135.         i = rand() & 3;
  136.         while (i--)
  137.         {
  138.             ent = G_Find (ent, FOFS(classname), "info_player_intermission");
  139.             if (!ent)    // wrap around the list
  140.                 ent = G_Find (ent, FOFS(classname), "info_player_intermission");
  141.         }
  142.     }
  143.  
  144.     VectorCopy (ent->s.origin, level.intermission_origin);
  145.     VectorCopy (ent->s.angles, level.intermission_angle);
  146.  
  147.     // move all clients to the intermission point
  148.     for (i=0 ; i<maxclients->value ; i++)
  149.     {
  150.         client = g_edicts + 1 + i;
  151.         if (!client->inuse)
  152.             continue;
  153.         MoveClientToIntermission (client);
  154.     }
  155. }
  156.  
  157.  
  158. /*
  159. ==================
  160. DeathmatchScoreboardMessage
  161.  
  162. ==================
  163. */
  164. void DeathmatchScoreboardMessage (edict_t *ent, edict_t *killer)
  165. {
  166.     char    entry[1024];
  167.     char    string[1400];
  168.     int        stringlength;
  169.     int        i, j, k;
  170.     int        sorted[MAX_CLIENTS];
  171.     int        sortedscores[MAX_CLIENTS];
  172.     int        score, total;
  173.     int        picnum;
  174.     int        x, y;
  175.     gclient_t    *cl;
  176.     edict_t        *cl_ent;
  177.     char    *tag;
  178.  
  179.     // sort the clients by score
  180.     total = 0;
  181.     for (i=0 ; i<game.maxclients ; i++)
  182.     {
  183.         cl_ent = g_edicts + 1 + i;
  184.         if (!cl_ent->inuse || game.clients[i].resp.spectator)
  185.             continue;
  186.         score = game.clients[i].resp.score;
  187.         for (j=0 ; j<total ; j++)
  188.         {
  189.             if (score > sortedscores[j])
  190.                 break;
  191.         }
  192.         for (k=total ; k>j ; k--)
  193.         {
  194.             sorted[k] = sorted[k-1];
  195.             sortedscores[k] = sortedscores[k-1];
  196.         }
  197.         sorted[j] = i;
  198.         sortedscores[j] = score;
  199.         total++;
  200.     }
  201.  
  202.     // print level name and exit rules
  203.     string[0] = 0;
  204.  
  205.     stringlength = strlen(string);
  206.  
  207.     // add the clients in sorted order
  208.     if (total > 12)
  209.         total = 12;
  210.  
  211.     for (i=0 ; i<total ; i++)
  212.     {
  213.         cl = &game.clients[sorted[i]];
  214.         cl_ent = g_edicts + 1 + sorted[i];
  215.  
  216.         picnum = gi.imageindex ("i_fixme");
  217.         x = (i>=6) ? 160 : 0;
  218.         y = 32 + 32 * (i%6);
  219.  
  220.         // add a dogtag
  221.         if (cl_ent == ent)
  222.             tag = "tag1";
  223.         else if (cl_ent == killer)
  224.             tag = "tag2";
  225.         else
  226.             tag = NULL;
  227.         if (tag)
  228.         {
  229.             Com_sprintf (entry, sizeof(entry),
  230.                 "xv %i yv %i picn %s ",x+32, y, tag);
  231.             j = strlen(entry);
  232.             if (stringlength + j > 1024)
  233.                 break;
  234.             strcpy (string + stringlength, entry);
  235.             stringlength += j;
  236.         }
  237.  
  238.         // send the layout
  239.         Com_sprintf (entry, sizeof(entry),
  240.             "client %i %i %i %i %i %i ",
  241.             x, y, sorted[i], cl->resp.score, cl->ping, (level.framenum - cl->resp.enterframe)/600);
  242.         j = strlen(entry);
  243.         if (stringlength + j > 1024)
  244.             break;
  245.         strcpy (string + stringlength, entry);
  246.         stringlength += j;
  247.     }
  248.  
  249.     gi.WriteByte (svc_layout);
  250.     gi.WriteString (string);
  251. }
  252.  
  253.  
  254. /*
  255. ==================
  256. DeathmatchScoreboard
  257.  
  258. Draw instead of help message.
  259. Note that it isn't that hard to overflow the 1400 byte message limit!
  260. ==================
  261. */
  262. void DeathmatchScoreboard (edict_t *ent)
  263. {
  264.     DeathmatchScoreboardMessage (ent, ent->enemy);
  265.     gi.unicast (ent, true);
  266. }
  267.  
  268.  
  269. /*
  270. ==================
  271. Cmd_Score_f
  272.  
  273. Display the scoreboard
  274. ==================
  275. */
  276. void Cmd_Score_f (edict_t *ent)
  277. {
  278.     ent->client->showinventory = false;
  279.     ent->client->showhelp = false;
  280.  
  281.     if (!deathmatch->value && !coop->value)
  282.         return;
  283.  
  284.     if (ent->client->showscores)
  285.     {
  286.         ent->client->showscores = false;
  287.         return;
  288.     }
  289.  
  290.     ent->client->showscores = true;
  291.     DeathmatchScoreboard (ent);
  292. }
  293.  
  294.  
  295. /*
  296. ==================
  297. HelpComputer
  298.  
  299. Draw help computer.
  300. ==================
  301. */
  302. void HelpComputer (edict_t *ent)
  303. {
  304.     char    string[1024];
  305.     char    *sk;
  306.  
  307.     if (skill->value == 0)
  308.         sk = "easy";
  309.     else if (skill->value == 1)
  310.         sk = "medium";
  311.     else if (skill->value == 2)
  312.         sk = "hard";
  313.     else
  314.         sk = "hard+";
  315.     //We are going to simplify this layout considerably.
  316.     // send the layout
  317.     Com_sprintf (string, sizeof(string),
  318.         "xv 32 yv 8 picn help "            // background
  319. //        "xv 202 yv 12 string2 \"%s\" "        // skill
  320. //        "xv 0 yv 24 cstring2 \"%s\" "        // level name
  321.         "xv 0 yv 54 cstring2 \"%s\" ",        // help 1
  322. //        "xv 0 yv 110 cstring2 \"%s\" "        // help 2
  323. //        "xv 50 yv 164 string2 \" kills     goals    secrets\" "
  324. //        "xv 50 yv 172 string2 \"%3i/%3i     %i/%i       %i/%i\" ", 
  325. //        sk,
  326. //        level.level_name,
  327.         game.helpmessage1);
  328. //        game.helpmessage2,
  329. //        level.killed_monsters, level.total_monsters, 
  330. //        level.found_goals, level.total_goals,
  331. //        level.found_secrets, level.total_secrets);
  332.  
  333.     gi.WriteByte (svc_layout);
  334.     gi.WriteString (string);
  335.     gi.unicast (ent, true);
  336. }
  337.  
  338.  
  339. /*
  340. ==================
  341. Cmd_Help_f
  342.  
  343. Display the current help message
  344. ==================
  345. */
  346. void Cmd_Help_f (edict_t *ent)
  347. {
  348.     // this is for backwards compatability
  349.     if (deathmatch->value)
  350.     {
  351.         Cmd_Score_f (ent);
  352.         return;
  353.     }
  354.  
  355.     ent->client->showinventory = false;
  356.     ent->client->showscores = false;
  357.  
  358.     if (ent->client->showhelp && (ent->client->pers.game_helpchanged == game.helpchanged))
  359.     {
  360.         ent->client->showhelp = false;
  361.         return;
  362.     }
  363.  
  364.     ent->client->showhelp = true;
  365.     ent->client->pers.helpchanged = 0;
  366.     HelpComputer (ent);
  367. }
  368.  
  369.  
  370. //=======================================================================
  371.  
  372. /*
  373. ===============
  374. G_SetStats
  375. ===============
  376. */
  377. void G_SetStats (edict_t *ent)
  378. {
  379.     gitem_t        *item;
  380.     int            index, cells;
  381.     int            power_armor_type;
  382.  
  383.     //
  384.     // health
  385.     //
  386.     ent->client->ps.stats[STAT_HEALTH_ICON] = level.pic_health;
  387.     ent->client->ps.stats[STAT_HEALTH] = ent->health;
  388.  
  389.     //
  390.     // ammo
  391.     //
  392.     if (!ent->client->ammo_index /* || !ent->client->pers.inventory[ent->client->ammo_index] */)
  393.     {
  394.         ent->client->ps.stats[STAT_AMMO_ICON] = 0;
  395.         ent->client->ps.stats[STAT_AMMO] = 0;
  396.     }
  397.     else
  398.     {
  399.         item = &itemlist[ent->client->ammo_index];
  400.         ent->client->ps.stats[STAT_AMMO_ICON] = gi.imageindex (item->icon);
  401.         ent->client->ps.stats[STAT_AMMO] = ent->client->pers.inventory[ent->client->ammo_index];
  402.     }
  403.     
  404.     //
  405.     // armor
  406.     //
  407.     power_armor_type = PowerArmorType (ent);
  408.     if (power_armor_type)
  409.     {
  410.         cells = ent->client->pers.inventory[ITEM_INDEX(FindItem ("cells"))];
  411.         if (cells == 0)
  412.         {    // ran out of cells for power armor
  413.             ent->flags &= ~FL_POWER_ARMOR;
  414.             gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
  415.             power_armor_type = 0;;
  416.         }
  417.     }
  418.  
  419.     index = ArmorIndex (ent);
  420.     if (power_armor_type && (!index || (level.framenum & 8) ) )
  421.     {    // flash between power armor and other armor icon
  422.         ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex ("i_powershield");
  423.         ent->client->ps.stats[STAT_ARMOR] = cells;
  424.     }
  425.     else if (index)
  426.     {
  427.         item = GetItemByIndex (index);
  428.         ent->client->ps.stats[STAT_ARMOR_ICON] = gi.imageindex (item->icon);
  429.         ent->client->ps.stats[STAT_ARMOR] = ent->client->pers.inventory[index];
  430.     }
  431.     else
  432.     {
  433.         ent->client->ps.stats[STAT_ARMOR_ICON] = 0;
  434.         ent->client->ps.stats[STAT_ARMOR] = 0;
  435.     }
  436.  
  437.     //
  438.     // pickup message
  439.     //
  440.     if (level.time > ent->client->pickup_msg_time)
  441.     {
  442.         ent->client->ps.stats[STAT_PICKUP_ICON] = 0;
  443.         ent->client->ps.stats[STAT_PICKUP_STRING] = 0;
  444.     }
  445.  
  446.     //
  447.     // timers
  448.     //
  449.     if (ent->client->quad_framenum > level.framenum)
  450.     {
  451.         ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_quad");
  452.         ent->client->ps.stats[STAT_TIMER] = (ent->client->quad_framenum - level.framenum)/10;
  453.     }
  454.     else if (ent->client->invincible_framenum > level.framenum)
  455.     {
  456.         ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_invulnerability");
  457.         ent->client->ps.stats[STAT_TIMER] = (ent->client->invincible_framenum - level.framenum)/10;
  458.     }
  459.     else if (ent->client->enviro_framenum > level.framenum)
  460.     {
  461.         ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_envirosuit");
  462.         ent->client->ps.stats[STAT_TIMER] = (ent->client->enviro_framenum - level.framenum)/10;
  463.     }
  464.     else if (ent->client->breather_framenum > level.framenum)
  465.     {
  466.         ent->client->ps.stats[STAT_TIMER_ICON] = gi.imageindex ("p_rebreather");
  467.         ent->client->ps.stats[STAT_TIMER] = (ent->client->breather_framenum - level.framenum)/10;
  468.     }
  469.     else
  470.     {
  471.         ent->client->ps.stats[STAT_TIMER_ICON] = 0;
  472.         ent->client->ps.stats[STAT_TIMER] = 0;
  473.     }
  474.  
  475.     //
  476.     // selected item
  477.     //
  478.     if (ent->client->pers.selected_item == -1)
  479.         ent->client->ps.stats[STAT_SELECTED_ICON] = 0;
  480.     else
  481.         ent->client->ps.stats[STAT_SELECTED_ICON] = gi.imageindex (itemlist[ent->client->pers.selected_item].icon);
  482.  
  483.     ent->client->ps.stats[STAT_SELECTED_ITEM] = ent->client->pers.selected_item;
  484.  
  485.     //
  486.     // layouts
  487.     //
  488.     ent->client->ps.stats[STAT_LAYOUTS] = 0;
  489.  
  490.     if (deathmatch->value)
  491.     {
  492.         if (ent->client->pers.health <= 0 || level.intermissiontime
  493.             || ent->client->showscores)
  494.             ent->client->ps.stats[STAT_LAYOUTS] |= 1;
  495.         if (ent->client->showinventory && ent->client->pers.health > 0)
  496.             ent->client->ps.stats[STAT_LAYOUTS] |= 2;
  497.     }
  498.     else
  499.     {
  500.         if (ent->client->showscores || ent->client->showhelp)
  501.             ent->client->ps.stats[STAT_LAYOUTS] |= 1;
  502.         if (ent->client->showinventory && ent->client->pers.health > 0)
  503.             ent->client->ps.stats[STAT_LAYOUTS] |= 2;
  504.     }
  505.  
  506.     //
  507.     // frags
  508.     //
  509.     ent->client->ps.stats[STAT_FRAGS] = ent->client->resp.score;
  510.  
  511.     //
  512.     // help icon / current weapon if not shown
  513.     //
  514.     if (ent->client->pers.helpchanged && (level.framenum&8) )
  515.         ent->client->ps.stats[STAT_HELPICON] = 0;//gi.imageindex ("i_help"); Gonna print something instead
  516.     else if ( (ent->client->pers.hand == CENTER_HANDED || ent->client->ps.fov > 91)
  517.         && ent->client->pers.weapon)
  518.         ent->client->ps.stats[STAT_HELPICON] = gi.imageindex (ent->client->pers.weapon->icon);
  519.     else
  520.         ent->client->ps.stats[STAT_HELPICON] = 0;
  521.  
  522.     ent->client->ps.stats[STAT_SPECTATOR] = 0;
  523. }
  524.  
  525. /*
  526. ===============
  527. G_CheckChaseStats
  528. ===============
  529. */
  530. void G_CheckChaseStats (edict_t *ent)
  531. {
  532.     int i;
  533.     gclient_t *cl;
  534.  
  535.     for (i = 1; i <= maxclients->value; i++) {
  536.         cl = g_edicts[i].client;
  537.         if (!g_edicts[i].inuse || cl->chase_target != ent)
  538.             continue;
  539.         memcpy(cl->ps.stats, ent->client->ps.stats, sizeof(cl->ps.stats));
  540.         G_SetSpectatorStats(g_edicts + i);
  541.     }
  542. }
  543.  
  544. /*
  545. ===============
  546. G_SetSpectatorStats
  547. ===============
  548. */
  549. void G_SetSpectatorStats (edict_t *ent)
  550. {
  551.     gclient_t *cl = ent->client;
  552.  
  553.     if (!cl->chase_target)
  554.         G_SetStats (ent);
  555.  
  556.     cl->ps.stats[STAT_SPECTATOR] = 1;
  557.  
  558.     // layouts are independant in spectator
  559.     cl->ps.stats[STAT_LAYOUTS] = 0;
  560.     if (cl->pers.health <= 0 || level.intermissiontime || cl->showscores)
  561.         cl->ps.stats[STAT_LAYOUTS] |= 1;
  562.     if (cl->showinventory && cl->pers.health > 0)
  563.         cl->ps.stats[STAT_LAYOUTS] |= 2;
  564.  
  565.     if (cl->chase_target && cl->chase_target->inuse)
  566.         cl->ps.stats[STAT_CHASE] = CS_PLAYERSKINS + 
  567.             (cl->chase_target - g_edicts) - 1;
  568.     else
  569.         cl->ps.stats[STAT_CHASE] = 0;
  570. }
  571.  
  572.